package com.bitcoin.scheduler.task;

import com.bitcoin.scheduler.domain.Bcc;
import com.bitcoin.scheduler.domain.Bcc24HourVolume;
import com.bitcoin.scheduler.domain.BccBasicDataCrawl;
import com.bitcoin.scheduler.domain.BccBasicInfo;
import com.bitcoin.scheduler.repository.BccBasicDataCrawlDao;
import com.bitcoin.scheduler.repository.BccBasicInfoDao;
import com.bitcoin.scheduler.service.BccBasicInfoService;
import com.bitcoin.scheduler.service.BccPriceInfoService;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.dozermapper.core.DozerBeanMapperBuilder;
import com.github.dozermapper.core.Mapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 币24小时交易量信息爬虫数据清洗任务
 */
@Service
@Slf4j
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
public class Bcc24HourVolumeTask implements Job {

    @Autowired
    private BccPriceInfoService priceInfoService;
    @Autowired
    private BccBasicInfoDao bccBasicInfoDao;

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        String listings = null;
        try {
            listings = Jsoup
                .connect("https://api.coinmarketcap.com/v2/listings/")
                .ignoreContentType(true)
                .execute().body();
            Map coinMap = new ObjectMapper().readValue(listings, Map.class);
            Map<String, String> mapping = Maps.newConcurrentMap();
            ArrayList<Map> coinList = (ArrayList) MapUtils.getObject(coinMap, "data");
            for (Map coin : coinList) {
                mapping.put(MapUtils.getString(coin, "id"), MapUtils.getString(coin, "symbol"));
            }
            Document document = Jsoup
                .connect("https://coinmarketcap.com/currencies/volume/24-hour")
                .get();

            Elements elements = document.select(".table-responsive > table > tbody > tr");
            String currentSymbol = null;
            List<Bcc24HourVolume> result = Lists.newArrayList();
            for (Element element : elements) {
                String bccName = element.attr("id");
                if (StringUtils.isNotEmpty(bccName)) {
                    Element logo = element.select("td > h3 > img").first();
                    String url = logo.attr("data-src");
                    String[] urlSplit = StringUtils.split(url, "/");
                    String[] last = StringUtils.split(urlSplit[urlSplit.length - 1], ".");
                    currentSymbol = MapUtils.getString(mapping, last[0]);
                    bccBasicInfoDao.existsBySymbol(currentSymbol);
                    if (!bccBasicInfoDao.existsBySymbol(currentSymbol)) {
                        currentSymbol = null;
                    }
                }
                else {
                    Elements elementsTd = element.select("td");
                    if (currentSymbol == null || elementsTd.size() != 6) {
                        continue;
                    }
                    Bcc24HourVolume volume = new Bcc24HourVolume();
                    volume.setSymbol(currentSymbol);
                    volume.setSource(elementsTd.get(1).text());
                    volume.setPair(elementsTd.get(2).text());
                    volume.setVolumeUsd(elementsTd.get(3).text());
                    volume.setPriceUsd(elementsTd.get(4).text());
                    volume.setVolumePercent(elementsTd.get(5).text());
                    volume.setId(volume.getSource() + "_" + volume.getPair());
                    volume.setUpdateDate(new Date());
                    result.add(volume);
                }
            }
            priceInfoService.getVolumeDao().saveAll(result);
        } catch (IOException e) {
            log.error("同步交易信息异常", e);
        }
    }
}
